﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;

namespace Common.Cryptography
{
    public static class CryptographyHelper
    {
        public static string CreateSalt(int size)
        {   
            //Generate a cryptographic random number.
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            byte[] buff = new byte[size];
            rng.GetBytes(buff);
            
            // Return a Base64 string representation of the random number.
            return Convert.ToBase64String(buff);
        }

        private static Rfc2898DeriveBytes GenerateKeyFromPassword(string strPassword)
        {
            if (String.IsNullOrEmpty(strPassword))
                throw new ArgumentNullException("strPassword");

            byte[] salt = System.Text.Encoding.UTF8.GetBytes(strPassword);
            salt = salt.Reverse().ToArray<byte>();

            Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(strPassword, salt);

            return key;
        }

        private static Rfc2898DeriveBytes GenerateKeyFromPassword(string strPassword, byte[] salt)
        {
            if (String.IsNullOrEmpty(strPassword))
                throw new ArgumentNullException("strPassword");
            if (salt.isNull() || salt.Length == 0)
                throw new ArgumentNullException("salt");

            Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(strPassword, salt);

            return key;
        }

        private static Rfc2898DeriveBytes GenerateKeyFromPassword(string strPassword, string salt)
        {
            if (String.IsNullOrEmpty(strPassword))
                throw new ArgumentNullException("strPassword");
            if (String.IsNullOrEmpty(salt))
                throw new ArgumentNullException("salt");

            byte[] saltbt = System.Text.Encoding.UTF8.GetBytes(salt);

            Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(strPassword, saltbt);

            return key;
        }

        public static byte[] GetKeyFromPassword(Rfc2898DeriveBytes keydef, int KeySize)
        {
            if (KeySize < 1)
                throw new ArgumentOutOfRangeException("KeySize");
            if (keydef.isNull())
                throw new ArgumentNullException("keydef");

            return keydef.GetBytes(KeySize);
        }

        public static byte[] GetKeyFromPassword(string strPassword, int KeySize)
        {
            var key = GenerateKeyFromPassword(strPassword);

            if (KeySize < 1)
                throw new ArgumentOutOfRangeException("KeySize");
            if (key.isNull())
                throw new ArgumentNullException("key");

            return key.GetBytes(KeySize);
        }

        public static byte[] GetIVFromPassword(Rfc2898DeriveBytes keydef, int IVSize)
        {
            if (IVSize < 1)
                throw new ArgumentOutOfRangeException("IVSize");
            if (keydef.isNull())
                throw new ArgumentNullException("keydef");

            return keydef.GetBytes(IVSize).Reverse().ToArray<byte>();
        }

        public static byte[] GetIVFromPassword(string strPassword, int IVSize)
        {
            var key = GenerateKeyFromPassword(strPassword);

            if (IVSize < 1)
                throw new ArgumentOutOfRangeException("IVSize");
            if (key.isNull())
                throw new ArgumentNullException("key");

            return key.GetBytes(IVSize).Reverse().ToArray<byte>();
        }
    }
}
